<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <script>
    class Dep {
      constructor() {
        this.subcribers = new Set();
      }

      deep() {
        if (activeUpdate) {
          this.subcribers.add(activeUpdate);
        }
      }

      notify() {
        this.subcribers.forEach(sub => sub());
      }
    }

    let activeUpdate;

    function autorun(update) {
      function wrappedUpdate() {
        activeUpdate = wrappedUpdate;
        update();
        activeUpdate = null;
      }
      wrappedUpdate();
    }

    const state = {
      count: 0
    };

    observe(state);

    autorun(() => {
      console.log(state.count);
    });

    function observe(obj) {
      Object.keys(obj).forEach(key => {
        let internalValue = obj[key];
        const dep = new Dep();

        Object.defineProperty(obj, key, {
          get() {
            dep.deep();
            return internalValue;
          },
          set(newValue) {
            const changed = internalValue !== newValue;
            internalValue = newValue;
            if (changed) {
              dep.notify();
            }
          }
        });
      });

      return obj;
    }
  </script>
</body>
</html>
